﻿# coding: utf-8

require 'sqlite3'
require 'json'
require_relative 'fundler_utils'

#TODO: make private methods... well, private!

module BookmarksReader

  include QueryConstants

  attr_reader :db

  MOZILLA_FIREFOX_CONF_DIR = File.expand_path('~') + '/.mozilla/firefox/'

  def find_bookmarks_by_tag(tag_id)
    query = QUERY_BY_TAG
    query.gsub(/@tag_id/,tag_id)
    db.execute(query) do |row|
      (result ||= []) << row
    end
  end

  def get_tags
    tags = {}
    db.execute(QUERY_FOR_TAGS).each do |row|
      tag = row.split('|')
      tags[tag[0]] = tag[1]
    end
    tags
  end
  
  def get_tag_by_id(id)
    query = QUERY_FOR_TAG_BY_ID
    query.gsub(/@tag_id/,id)
    db.get_first_row(query)
  end

  def stored_bookmarks
    # humm... I don't like this choice
    @stored_bookmarks ||= get_bookmarks_with_tags
  end

  def bookmarks_count
    stored_bookmarks.size
  end

  def get_bookmarks_with_tags
    all = []
    @stored_bookmarks = {}
    if db
      db.execute(QUERY_FOR_SIMPLE_BOOKMARKS) do |bookmark|
        all << bookmark
      end
      all.each do |bookmark|
        bookmark_id, bookmark_fk, bookmark_title = bookmark
        if bookmark_fk
          link_query = QUERY_FOR_LINK.sub(/@fk_id/, bookmark_fk.to_s)
          links = db.execute(link_query) 
          links.each do |link|
            link_id, link_fk, link_parent = link
            tag_query = QUERY_FOR_TAG_BY_ID.gsub(/@parent/, link_parent.to_s)
            db.execute(tag_query) do |tag|
              tag_id, tag_title = tag
              @stored_bookmarks[bookmark_id] = { tag: tag_title, title: bookmark_title }
            end
          end
        end
      end
    end
    @stored_bookmarks.extend(HashBookmarksUtil)
  end

  def get_bookmarks_with_url_title_descr_tag
    unless stored_bookmarks.empty?
      db.execute(BOOKMARKS_QUERY).each do |bookmark|
        url, title, id, description = bookmark
        @stored_bookmarks[id].merge!({url: url, description: description})
      end
    end
    @stored_bookmarks
  end

  # +drop_bookmarks+ browse the home directory of the current user,
  # locate the +places.sqlite+ db_file generated by Firefox and
  # retrieve all the bookmarks stored.
  def drop_bookmarks(format = :txt)
    output = []
    if db
      get_bookmarks_with_url_title_descr_tag.each_with_index do |row, index|
        case format.intern
        when :txt
          output << "#{index}: #{row}"
          output << '---'
        when :html
          puts "TODO"
        when :markdown
          puts "TODO"
        when :json
          output << row.to_json
        else
          # exit 1
        end
      end
    end
    File.open("./bookmarks_dump.#{format.to_s}", 'w') do |file|
      file.puts output
    end
  end
  
  def locate_places
    begin
      dot_firefox = Dir.open(MOZILLA_FIREFOX_CONF_DIR)
      profile_dir = dot_firefox.select {|dir| dir =~ /.*default/}
      db_file = MOZILLA_FIREFOX_CONF_DIR + profile_dir.join + '/places.sqlite'
    rescue Errno::ENOENT
      puts "no db_bookmarks found"
      # exit 1
      nil
    end
  end
  
  def db
    @db ||= SQLite3::Database.new(locate_places) if locate_places
  end
  
  def dump_places
    FileUtils.cp(locate_places, pwd)
  end

end # BookmarksReader

__END__

select id,fk,title,parent from moz_bookmarks;
...
1983|2509|The Places database | MDN|2
1984|2509||1144
1933|1387|SQLite Home Page|2
1934|1387||1144
...

select id,fk,title from moz_bookmarks where parent = 2;
=> 1933|1387|SQLite Home Page

select id,fk,parent from moz_bookmarks where title is null and fk = 1387;
1934|1387|1144

select title from moz_bookmarks where parent = 4 AND id = 1144;
=> coding

